"""
抽象工厂模式（Abstract Factory Pattern）是围绕一个超级工厂创建其他工厂。该超级工厂又称为其他工厂的工厂。
这种类型的设计模式属于创建型模式，它提供了一种创建对象的最佳方式。
在抽象工厂模式中，接口是负责创建一个相关对象的工厂，不需要显式指定它们的类。每个生成的工厂都能按照工厂模式提供对象。
抽象工厂模式提供了一种创建一系列相关或相互依赖对象的接口，而无需指定具体实现类。通过使用抽象工厂模式，可以将客户端与具体产品的创建过程解耦，
使得客户端可以通过工厂接口来创建一族产品。
意图：
    提供一个创建一系列相关或相互依赖对象的接口，而无需指定它们的具体类。
适用性：
    当系统需要创建多个相关或依赖的对象，而不需要指定具体类时。
结构：
    抽象工厂（Abstract Factory）：声明了一组用于创建产品对象的方法，每个方法对应一种产品类型。抽象工厂可以是接口或抽象类。
    具体工厂（Concrete Factory）：实现了抽象工厂接口，负责创建具体产品对象的实例。
    抽象产品（Abstract Product）：定义了一组产品对象的共同接口或抽象类，描述了产品对象的公共方法。
    具体产品（Concrete Product）：实现了抽象产品接口，定义了具体产品的特定行为和属性。
"""
from abc import ABC, abstractmethod


# 抽象产品 A
class Button(ABC):
    @abstractmethod
    def click(self):
        pass


# 具体产品 A1
class WindowsButton(Button):
    def click(self):
        print('Windows button clicked.')


# 具体产品 A2
class MacOSButton(Button):
    def click(self):
        print('macOS button clicked.')


# 抽象产品B
class Checkbox(ABC):
    @abstractmethod
    def check(self):
        pass


# 具体产品 B1
class WindowCheckbox(Checkbox):
    def check(self):
        print('Windows checkbox checked.')


# 具体产品 B2
class MacOSCheckbox(Checkbox):
    def check(self):
        print('macOS checkbox checked.')


# 抽象工厂
class GUIFactory(ABC):
    @abstractmethod
    def create_button(self):
        pass

    @abstractmethod
    def create_checkbox(self):
        pass


# 具体工厂A
class WindowsFactory(GUIFactory):
    def create_button(self) -> Button:
        return WindowsButton()

    def create_checkbox(self) -> Checkbox:
        return WindowCheckbox()


# 具体工厂B
class MacOSFactory(GUIFactory):
    def create_button(self) -> Button:
        return MacOSButton()

    def create_checkbox(self) -> Checkbox:
        return MacOSCheckbox()


def client_code(factory: GUIFactory):
    button = factory.create_button()
    checkbox = factory.create_checkbox()

    button.click()
    checkbox.check()


if __name__ == '__main__':
    windows_factory = WindowsFactory()
    client_code(windows_factory)

    macos_factory = MacOSFactory()
    client_code(macos_factory)
